# 装饰器是一种用于扩展函数或方法功能的高阶函数,可以在不修改原函数代码的前提下动态添加功能.装饰器通常用于跨切关注点（如日志记录、权限验证等）的实现.

'''
@decorator
def func():
    pass
# 等价于
def func():
    pass
func = decorator(func)

'''

def simple_decorator(func):
    def wrapper():
        print("Before function call")
        result = func()
        print("After function call")
        return result
    return wrapper

@simple_decorator
def say_hello():
    print("Hello!")

say_hello()
# 输出：
# Before function call
# Hello!
# After function call

#函数装饰器  函数装饰器是最常见的装饰器,用于装饰函数,增强函数的功能.
def timing_decorator(func):
    import time
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} took {end_time - start_time} seconds")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(2)
    return "Function complete"

print(slow_function())
# 输出：
# slow_function took 2.0 seconds
# Function complete


# 类装饰器   类装饰器用于装饰类,常用于修改类的行为或为类添加功能.
def class_decorator(cls):
    class NewClass(cls):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            print("Class instantiated")

        def new_method(self):
            return "New method"
    return NewClass

@class_decorator
class MyClass:
    def __init__(self, value):
        self.value = value

    def display_value(self):
        print(f"Value: {self.value}")

obj = MyClass(10)
obj.display_value()
print(obj.new_method())
# 输出：
# Class instantiated
# Value: 10
# New method
# 无参数装饰器 无参数装饰器是最简单的装饰器,不接受任何参数,仅用于装饰函数或类.

# 带参数装饰器  带参数装饰器接受参数,可以根据传入的参数动态修改装饰器的行为.

def repeat_decorator(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat_decorator(3)
def say_hello():
    print("Hello!")

say_hello()
# 输出：
# Hello!
# Hello!
# Hello!


# 装饰器的实际应用
# 日志记录 装饰器可以用于记录函数的调用日志,方便调试和监控.

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function {func.__name__}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} finished")
        return result
    return wrapper

@log_decorator
def add(a, b):
    return a + b

print(add(3, 4))
# 输出：
# Calling function add
# Function add finished
# 7

# 权限验证  装饰器可以用于检查用户权限,确保只有具有相应权限的用户才能执行特定操作.
def permission_required(permission):
    def decorator(func):
        def wrapper(user, *args, **kwargs):
            if user.has_permission(permission):
                return func(user, *args, **kwargs)
            else:
                raise PermissionError("Permission denied")
        return wrapper
    return decorator

class User:
    def __init__(self, permissions):
        self.permissions = permissions

    def has_permission(self, permission):
        return permission in self.permissions

@permission_required('admin')
def delete_user(user, user_id):
    print(f"User {user_id} deleted")

admin = User(['admin'])
guest = User([])

delete_user(admin, 1)  # 输出：User 1 deleted
delete_user(guest, 1)  # 抛出：PermissionError: Permission denied

# 缓存  装饰器可以用于缓存函数的结果,提高函数的执行效率.

def cache_decorator(func):
    cache = {}
    def wrapper(*args):
        if args in cache:
            return cache[args]
        result = func(*args)
        cache[args] = result
        return result
    return wrapper

@cache_decorator
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))  # 输出：55



# 装饰器的优缺点
# 优点
# 代码重用:装饰器允许跨多个函数或类重用相同的功能代码.
# 增强功能:可以在不修改原有代码的前提下增强函数或类的功能.
# 提高可读性:将额外的功能逻辑分离到装饰器中,提高核心代码的可读性.
# 缺点
# 复杂性:过多使用装饰器可能会增加代码的复杂性,尤其是多个装饰器嵌套使用时.
# 调试困难:装饰器可能会隐藏原函数的调用堆栈信息,增加调试难度.